﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using static System.Collections.Specialized.BitVector32;

namespace Apewer.Models
{

    /// <summary>INI 节。</summary>
    [Serializable]
    public sealed class IniSection : ICollection<TextField>, IEnumerable<TextField>, IToJson
    {

        private List<TextField> _fields = new List<TextField>();

        /// <summary>节的名称（不含方括号）。</summary>
        public string Name { get; set; }

        /// <summary></summary>
        public override string ToString() => $"Name = \"{Name}\", Count = {_fields.Count}";

        #region ICollection<TextField>

        /// <summary></summary>
        public int Count { get => _fields.Count; }

        /// <summary>集合是只读的。</summary>
        /// <value>此值始终为 FALSE。</value>
        public bool IsReadOnly { get => false; }

        /// <summary>添加字段。</summary>
        /// <exception cref="ArgumentNullException" />
        public void Add(TextField item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            _fields.Add(item);
        }

        /// <summary>清空字段。</summary>
        public void Clear() => _fields.Clear();

        /// <summary>检查此集合是否包含指定的字段。</summary>
        public bool Contains(TextField item) => _fields.Contains(item);

        /// <summary>复制字段到数组中。</summary>
        /// <exception cref="ArgumentException" />
        /// <exception cref="ArgumentNullException" />
        /// <exception cref="ArgumentOutOfRangeException" />
        public void CopyTo(TextField[] array, int arrayIndex)
        {
            if (array == null) throw new ArgumentNullException(nameof(array));
            if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex));
            if (array.Length - arrayIndex < _fields.Count) throw new ArgumentException("目标数组长度不足。");

            _fields.CopyTo(array, arrayIndex);
        }

        /// <summary>移除字段。</summary>
        public bool Remove(TextField item)
        {
            var removed = false;
            while (_fields.Contains(item))
            {
                _fields.Remove(item);
                removed = true;
            }
            return removed;
        }

        #endregion

        #region Enumerable

        /// <summary></summary>
        public IEnumerator<TextField> GetEnumerator() => new Enumerator<TextField>(i => i < _fields.Count ? new Class<TextField>(_fields[i]) : null);

        /// <summary></summary>
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

        #endregion

        #region IToJson

        /// <summary></summary>
        public Json ToJson()
        {
            var fields = Json.NewObject();
            foreach (var field in _fields)
            {
                fields.SetProperty(field.Name, field.Value);
            }

            var json = Json.NewObject();
            json.SetProperty("name", Name);
            json.SetProperty("fields", fields);

            return json;
        }

        #endregion

        /// <summary>检查此集合是否包含指定的字段。</summary>
        /// <param name="name">字段名称。</param>
        public bool Contains(string name)
        {
            var count = _fields.Count;
            for (var i = 0; i < count; i++)
            {
                if (_fields[0].Name == name) return true;
            }
            return false;
        }

        /// <summary>获取字段。</summary>
        /// <exception cref="ArgumentOutOfRangeException" />"
        public TextField GetField(int index)
        {
            if (index < 0 || index >= _fields.Count) throw new ArgumentOutOfRangeException(nameof(index));
            return _fields[index];
        }

        /// <summary></summary>
        public string GetValue(string name)
        {
            if (name.IsEmpty()) throw new ArgumentNullException(nameof(name));

            foreach (var field in _fields)
            {
                if (field.Name == name) return field.Value;
            }
            return null;
        }

        /// <summary></summary>
        public void SetValue(string name, string value)
        {
            if (name.IsEmpty()) throw new ArgumentNullException(nameof(name));

            var count = _fields.Count;
            var setted = false;
            for (var i = 0; i < count; i++)
            {
                if (_fields[i].Name == name)
                {
                    _fields[i].Value = value;
                    setted = true;
                }
            }

            if (!setted)
            {
                var field = new TextField(name, value);
                _fields.Add(field);
            }
        }

        /// <summary>获取或设置字段。</summary>
        public string this[string name] { get => GetValue(name); set => SetValue(name, value); }

        /// <summary></summary>
        public IniSection() { }

        /// <summary></summary>
        public IniSection(string name) : this()
        {
            this.Name = name;
        }

        /// <summary></summary>
        /// <exception cref="ArgumentNullException" />
        public IniSection(string name, IEnumerable<TextField> fields) : this(name)
        {
            if (fields == null) throw new ArgumentNullException(nameof(fields));
            _fields.AddRange(fields.Map(x => x == null ? null : new TextField(x.Name, x.Value)).FindAll(x => x != null));
        }

        /// <summary></summary>
        /// <exception cref="ArgumentNullException" />
        public IniSection(IEnumerable<TextField> fields) : this(null, fields) { }

        /// <summary></summary>
        /// <exception cref="ArgumentNullException" />
        public IniSection(string name, IEnumerable<KeyValuePair<string, string>> fields) : this(name)
        {
            if (fields == null) throw new ArgumentNullException(nameof(fields));
            _fields.AddRange(fields.Map(x => new TextField(x)));
        }

        /// <summary></summary>
        /// <exception cref="ArgumentNullException" />
        public IniSection(IEnumerable<KeyValuePair<string, string>> fields) : this(null, fields) { }

    }

}
